#include "main.h"
#include "dht11.h"
#include "delay.h"
//定义 DHT11 连接的 GPIO 端口和引脚，方便移植 
#define DHT11_PORT GPIOC
#define DHT11_PIN GPIO_PIN_10

/*
**@Brief 通过 DHT11 传感器传递一次温度和湿度数据
**
**@Params
** 	temp 用于接受温度
** 	humi 用于接受湿度
**
**@Retval
** 采集成功返回 0， 否则返回非零（错误码） 返回 1 表示 DHT11 未响应（DHT11 故障或连接异常）2 表示校验失败（可能存在干扰）
**
**@Example
**
**	float t,h;
**	if(DHT11_Get(&t,&h) == 0)
**	{
**		//处理温湿度数据
** 		//......
**	}
**
**
*/
int8_t DHT11_Get(float* temp, uint8_t* humi)
{
	int8_t i,j,data[5];
	//将目标引脚设置位开漏输出模式
	GPIO_InitTypeDef conf;
	conf.Pin = DHT11_PIN;
	conf.Mode = GPIO_MODE_OUTPUT_OD;
	conf.Pull = GPIO_NOPULL;
	conf.Speed = GPIO_SPEED_FREQ_LOW;
	HAL_GPIO_Init(DHT11_PORT,&conf);
	
	//向 DHT11 发出信号
	
	HAL_GPIO_WritePin(DHT11_PORT,DHT11_PIN,GPIO_PIN_RESET);
	HAL_Delay(20);
	
	//切换到输入模式，释放总线
	conf.Mode = GPIO_MODE_INPUT;
	HAL_GPIO_Init(DHT11_PORT,&conf);

	//延时60us
	Delay_US(60);
	
	//读取 DHT11 响应信号
	//如果 DHT11 未响应，就返回 1，说明 DHT11 传感器故障或连接异常
	
	if(HAL_GPIO_ReadPin(DHT11_PORT,DHT11_PIN) == GPIO_PIN_SET )
		return 1;
	
	//等待 DHT11 的低电平响应信号结束
	while(HAL_GPIO_ReadPin(DHT11_PORT,DHT11_PIN) == GPIO_PIN_RESET);
	
	//延时 120us
	Delay_US(120);
	
	//逐位接收温湿度数据（共 40 位，高位先出）
	

	for(i = 0; i < 5; i++)
	{
		data[i] = 0;
		for(j = 0 ; j < 8; j++)
		{
		
			//等待 0 或 1 信号的前导低电平结束
		 while (HAL_GPIO_ReadPin(DHT11_PORT, DHT11_PIN) == GPIO_PIN_RESET)
		 {
		 
		 }

            data[i] <<= 1;
			
			//延时50us
			Delay_US(50);
		
		 if(HAL_GPIO_ReadPin(DHT11_PORT, DHT11_PIN) == GPIO_PIN_SET)
		 {
		 
			data[i]+= 1;
			Delay_US(40);
		 }
		}
	}
	
	//检查校验和，如果校验失败，就返回2，说明通信存在干扰
	if(data[0] + data[1] + data[2] + data[3] != data[4] )
	return 2;
	
	//计算温度和湿度
	if(humi != NULL) *humi = data[0];
	if(temp != NULL)
	{
		*temp = data[2] + (float)(data[3] & 0x7F) /10;
		if(data[3] & 0x80) *temp = -*temp;
	
	}
	
	return 0;
}

